package week4;


import jsjf.exceptions.ElementNotFoundException;
import jsjf.exceptions.EmptyCollectionException;
import week2.LinearNode;

import java.util.Iterator;

public class LinkedList<T> implements ListADT<T>, Iterable<T>{
    protected int count;
    protected LinearNode<T> head, tail;
    protected int modCount;

    public LinkedList()
    {
        count = 0;
        head = tail = null;
        modCount = 0;
    }

    @Override
    public T removeFirst() {
        if(isEmpty())
        {
            throw new EmptyCollectionException("LinkedList");
        }

        LinearNode<T> current = head;
        head = current.getNext();

        count--;
        modCount++;

        return current.getElement();
    }

    @Override
    public T removeLast() {
        LinearNode<T> previous = null;
        LinearNode<T> current = head;

        if(isEmpty())
        {
            throw new EmptyCollectionException("LinkedList");
        }
        while (current != null)
        {
            previous = current;
            current = current.getNext();
        }
        if (size() == 1)
            head = tail = null;
        else {
            tail = previous;
            tail.setNext(null);
        }
        count--;
        modCount++;

        return current.getElement();
    }

    @Override
    public T remove(T targetelement) throws EmptyCollectionException, ElementNotFoundException {
        if(isEmpty())
        {
            throw new EmptyCollectionException("LinkedList");
        }

        boolean found = false;
        LinearNode<T> previous = null;
        LinearNode<T> current = head;

        while (current != null && !found)
        {
            if (targetelement.equals(current.getElement()))
            {
                found = true;
            }
            else
            {
                previous = current;
                current = current.getNext();
            }
        }

        if (!found)
        {
            throw new ElementNotFoundException("LinkedList");
        }

        if (size()==1)  // 列表中只有一个元素
        {
            head = tail = null;
        }
        else if (current.equals(tail))  //  目标在头
        {
            head = current.getNext();
        }
        else if (current.equals(tail))  //  目标在尾
        {
            tail = previous;
            tail.setNext(null);
        }
        else   // 目标在中间
        {
            previous.setNext(current.getNext());
        }

        count--;
        modCount++;

        return current.getElement();
    }

    @Override
    public T first() {
        if (isEmpty()){
            throw new EmptyCollectionException("LinkedList");
        }

        T result = head.getElement();
        return result;
    }

    @Override
    public T last() {
        if (isEmpty()){
            throw new EmptyCollectionException("LinkedList");
        }

        LinearNode<T> temp = head;
        while(temp.getNext()!= null) {
            temp = temp.getNext();
        }

        return temp.getElement();
    }

    @Override
    public boolean contains(T target) {
        LinearNode<T> current = head;
        while (current.getNext() != null) {
            current = current.getNext();
        }

        if (target.equals(current.getElement())) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public boolean isEmpty() {
        return count == 0;
    }

    @Override
    public int size() {
        return count;
    }

    @Override
    public Iterator<T> iterator() {
        return null;
    }

    public String toString()
    {
        LinearNode<T> temp;
        temp = head;
        String result = "";
        while(temp != null)
        {
            result += temp.getElement() + " ";
            temp = temp.getNext();
        }
        return result;
    }
}
